import axios from 'axios'
import type { AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios'
import type { ResultData } from '@/@types/index.type'
import { tokenUtil } from './auth'
import store from '@/stores/index'

// export default request

const config: AxiosRequestConfig = {
  baseURL: import.meta.env.VITE_APP_BASE_URL
}

class Request {
  instance: AxiosInstance
  constructor() {
    this.instance = axios.create(config)

    // 请求拦截器
    this.instance.interceptors.request.use(
      config => {
        const token = tokenUtil.getToken()
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }
        if (config.method === 'post') {
          config.headers['Content-Type'] = 'application/json'
        }
        return config
      },
      error => {
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        const { code, message } = response.data

        switch (code) {
          case 500:
            window.$message.error(message || '服务器错误')
            return Promise.reject(response.data)
          case 401:
            window.$message.error(message)
            const { user } = store()
            user.logout()
            return
          case 403:
            window.$message.error('无权限访问')
            return
          default:
            return response.data
        }
      },
      error => {
        console.log(error)

        const { message } = error.response.data
        window.$message.error(message || '服务器繁忙')
        return Promise.reject(error)
      }
    )
  }

  get<T>(url: string, params?: any, config?: AxiosRequestConfig): Promise<ResultData<T>> {
    return this.instance.get(url, { params, ...config })
  }

  post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ResultData<T>> {
    return this.instance.post(url, data, config)
  }

  put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ResultData<T>> {
    return this.instance.put(url, data, config)
  }

  delete<T>(url: string, config?: AxiosRequestConfig): Promise<ResultData<T>> {
    return this.instance.delete(url, config)
  }
}

const request = new Request()

export default request
